package com.smartian.scan.filesearch;

import android.content.Context;

import com.smartian.scan.filesearch.dispatchers.PrioritySearchTaskDispatcher;
import com.smartian.scan.filesearch.dispatchers.SearchTaskDispatcher;
import com.smartian.scan.filesearch.dispatchers.DeepSearchTaskDispatcher;
import com.smartian.scan.filesearch.dispatchers.TreeSearchTaskDispatcher;
import com.smartian.scan.filesearch.impl.callbacks.LogOpCallback;
import com.smartian.scan.filesearch.interfaces.IDispatcher;
import com.smartian.scan.filesearch.interfaces.IFilter;
import com.smartian.scan.filesearch.interfaces.ISearchCallback;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;


public class DispatcherManager {


    public static final int SEARCH_DISPATCHER_COMMON_TASK = 1;
    public static final int SEARCH_DISPATCHER_PRIORITY_TASK = 2;
    public static final int SEARCH_DISPATCHER_SINGLE_TASK = 3;
    public static final int SEARCH_DISPATCHER_TREE_TASK = 4;

    private final Queue<IDispatcher> dispatchers = new LinkedBlockingQueue<>();
    private static volatile DispatcherManager instance;

    public static DispatcherManager shareInstance() {
        if (instance == null) {
            synchronized (DispatcherManager.class) {
                if (instance == null) {
                    instance = new DispatcherManager();
                }
            }
        }
        return instance;
    }


    public void addDispatcher(IDispatcher dispatcher) {
        dispatchers.add(dispatcher);
    }

    public void removeDispatcher(IDispatcher dispatcher) {
        dispatchers.remove(dispatcher);
    }


    public void shutdownDispatcher(IDispatcher dispatcher) {
        if (dispatcher == null) return;
        removeDispatcher(dispatcher);
        dispatcher.shutdown();
    }

    public void shutdownDispatchers() {
        Iterator<IDispatcher> it = dispatchers.iterator();
        if (it == null || !it.hasNext()) return;
        do {
            IDispatcher dispatcher = it.next();
            dispatcher.shutdown();
            it.remove();

        } while (it.hasNext());
    }



    public static class TaskBuilder{

        private int  engineType;
        private long timeout;
        private List<String> dirs;
        private List<IFilter> filters;
        private ISearchCallback callback;
        private Context context;

        public TaskBuilder(){
            filters = new ArrayList<>();
            timeout = 0l;
            dirs = new ArrayList<>();
            engineType = SEARCH_DISPATCHER_COMMON_TASK;
            callback = new LogOpCallback();
        }

        public TaskBuilder callback(ISearchCallback callback) {
            this.callback = callback;
            return this;
        }

        public TaskBuilder addFilter(IFilter filter){
            filters.add(filter);
            return this;
        }
        public TaskBuilder addFilters(List<IFilter> filters){
            if(filters!=null) {
                this.filters.addAll(filters);
            }
            return this;
        }

        public TaskBuilder context(Context context) {
            if(context!=null) {
                this.context = context.getApplicationContext();
            }
            return this;
        }

        public TaskBuilder timeout(long timeout){
            this.timeout  = timeout;
            return this;
        }

        public TaskBuilder engineType(int engineType) {
            this.engineType = engineType;
            return this;
        }

        public TaskBuilder dirPaths(List<String> dirs){
            this.dirs  = dirs;
            return this;
        }


        public IDispatcher build() {
            IDispatcher dispatcher = buildDispatcher(engineType);
            if(dispatcher==null) {
                return null;
            }

            SearchTaskManager.setContext(context);

            dispatcher.setBeginPaths(this.dirs);
            dispatcher.setTimeout(this.timeout);
            dispatcher.setFilters(this.filters);
            dispatcher.setCallback(this.callback);

            DispatcherManager.shareInstance().addDispatcher(dispatcher);
            return dispatcher;
        }



        public IDispatcher buildDispatcher(int engineType) {
            if(engineType== SEARCH_DISPATCHER_COMMON_TASK){
                return new SearchTaskDispatcher();
            }else if(engineType== SEARCH_DISPATCHER_PRIORITY_TASK){
                return new PrioritySearchTaskDispatcher();
            }
            else if(engineType==SEARCH_DISPATCHER_SINGLE_TASK){
                return new DeepSearchTaskDispatcher();
            }
            return new TreeSearchTaskDispatcher();
        }


    }
}
